﻿/****************************************************************************
 * Application   : Freekick Desktop Manager
 * Author        : sfreekick
 * Email         : sfreekick@gmail.com
 * Copyright     : (C) 2008 sfreekick
 * **************************************************************************/

/****************************************************************************
 *  This file is part of FreeKickManager.
 *
 *  FreeKickManager is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  FreeKickManager is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with FreeKickManager. If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using HtmlAgilityPack;
using System.Text.RegularExpressions;

namespace FreeKickManager
{
    public class CargadorXml
    {
        public static InfoEquipo cargarInformacionEquipo(string xml)
        {
            InfoEquipo info = null;

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);

                info = new InfoEquipo();

                info.idEquipo = Convert.ToInt32(doc.DocumentElement.Attributes["id"].Value);
                info.nombre = doc.DocumentElement.SelectSingleNode("name").InnerText;

                info.estadio = doc.DocumentElement.SelectSingleNode("arena/name").InnerText;
                info.aforo = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("arena/total").InnerText);

                info.popularidadSenior = doc.DocumentElement.SelectSingleNode("senior/popularity").InnerText;
                info.espectaculoSenior = doc.DocumentElement.SelectSingleNode("senior/flair").InnerText;

                info.popularidadJuvenil = doc.DocumentElement.SelectSingleNode("youth/popularity").InnerText;
                info.espectaculoJuvenil = doc.DocumentElement.SelectSingleNode("youth/flair").InnerText;

                info.liga = doc.DocumentElement.SelectSingleNode("league").InnerText;

                info.divisionSenior = doc.DocumentElement.SelectSingleNode("senior/division").InnerText;
                info.serieSenior = doc.DocumentElement.SelectSingleNode("senior/series").InnerText;

                info.divisionJuvenil = doc.DocumentElement.SelectSingleNode("youth/division").InnerText;
                info.serieJuvenil = doc.DocumentElement.SelectSingleNode("youth/series").InnerText;

                info.rankingNacionalSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/league_rank").InnerText);
                info.equiposNacionalSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/league_clubs").InnerText);
                info.rankingMundialSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/world_rank").InnerText);
                info.equiposMundialSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/world_clubs").InnerText);

                info.rankingNacionalJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/league_rank").InnerText);
                info.equiposNacionalJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/league_clubs").InnerText);
                info.rankingMundialJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/world_rank").InnerText);
                info.equiposMundialJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/world_clubs").InnerText);
            }
            catch (XmlException ex)
            {
                MessageBox.Show("Se ha producido un error durante la carga del fichero XML (Info). Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return info;
        }

        public static List<Partido> cargarListaPartidos(string xml)
        {
            List<Partido> listaPartidos = null;

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);

                XmlNodeList nodosPartidos = doc.DocumentElement.SelectNodes("match");

                listaPartidos = new List<Partido>();

                foreach (XmlNode nodoPartido in nodosPartidos)
                {
                    Partido part = new Partido();

                    part.id = nodoPartido.Attributes["id"].Value;
                    part.fecha = nodoPartido.SelectSingleNode("date").InnerText;
                    part.competicion = nodoPartido.SelectSingleNode("type").InnerText;
                    part.categoria = nodoPartido.SelectSingleNode("squad").InnerText;
                    part.temporada = nodoPartido.SelectSingleNode("season").InnerText; ;

                    part.idPropio = doc.GetElementsByTagName("team")[0].Attributes["id"].Value;
                    part.nombrePropio = doc.GetElementsByTagName("team")[0].SelectSingleNode("name").InnerText;

                    part.idOponente = nodoPartido.SelectSingleNode("opponent").Attributes["id"].Value;
                    part.nombreOponente = nodoPartido.SelectSingleNode("opponent/name").InnerText;
                    part.jugado = nodoPartido.SelectSingleNode("played").InnerText;
                    part.campo = nodoPartido.SelectSingleNode("field").InnerText;

                    if (part.jugado.Equals("true"))
                        part.resultado = nodoPartido.SelectSingleNode("result/final").InnerText;

                    listaPartidos.Add(part);
                }
            }
            catch (XmlException ex)
            {
                MessageBox.Show("Se ha producido un error durante la carga del fichero XML (Partidos). Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return listaPartidos;
        }

        public static List<Equipo> cargarClasificacion(string xml)
        {
            List<Equipo> clasificacion = null;

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);

                XmlNodeList listaEquipos = doc.DocumentElement.SelectNodes("club");

                clasificacion = new List<Equipo>();

                foreach (XmlNode nodoEquipo in listaEquipos)
                {
                    Equipo eq = new Equipo();

                    eq.id = Convert.ToInt32(nodoEquipo.Attributes["id"].Value);
                    eq.nombre = nodoEquipo.SelectSingleNode("name").InnerText;
                    eq.ganados = Convert.ToInt32(nodoEquipo.SelectSingleNode("matches").Attributes["win"].Value);
                    eq.empatados = Convert.ToInt32(nodoEquipo.SelectSingleNode("matches").Attributes["draw"].Value);
                    eq.perdidos = Convert.ToInt32(nodoEquipo.SelectSingleNode("matches").Attributes["loss"].Value);
                    eq.golesFavor = Convert.ToInt32(nodoEquipo.SelectSingleNode("aggregate").Attributes["for"].Value);
                    eq.golesContra = Convert.ToInt32(nodoEquipo.SelectSingleNode("aggregate").Attributes["against"].Value);
                    eq.puntos = Convert.ToInt32(nodoEquipo.SelectSingleNode("points").InnerText);

                    clasificacion.Add(eq);
                }
            }
            catch (XmlException ex)
            {
                MessageBox.Show("Se ha producido un error durante la carga del fichero XML (Equipos). Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return clasificacion;
        }

        public static ReportePartido cargarReporte(Partido part, string rutaXmlEntrada)
        {
            generarHtmlPartido(rutaXmlEntrada, "temp\\partido-aux.html");

            ReportePartido reporte = parsearPartido(part, "temp\\partido-aux.html");

            return reporte;
        }

        private static void generarHtmlPartido(string rutaXmlSalida, string rutaHtmlSalida)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(rutaXmlSalida);

            XmlNodeList listaNodos = doc.GetElementsByTagName("text");

            if (listaNodos.Count > 0)
            {
                XmlNode nodoText = listaNodos[0];

                string html = nodoText.InnerText;
                html = "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"layout.css\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"text.css\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"fixed.css\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"menu.css\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"match_report.css\" /></head>"   //<body style=\"font-family: verdana, arial, helvetica, sans-serif;font-size:10px;color:#FFFFFF;margin:10px;padding:0px;background-color:#060;\">"
                    + html
                    + "</body></html>";

                html = html.Replace("&lt;", "<");
                html = html.Replace("&gt;", ">");
                html = html.Replace("&amp;", "&");
                html = html.Replace("&quot;", "\"");

                //html = html.Replace("<a href=\"?action=special&value=View_Player&value2=", "<a href=\"otrosjugadores.html#");

                //Se realiza la traducción del partido
                html = traducirPartido(html);

                StreamWriter sw = new StreamWriter(rutaHtmlSalida, false, Encoding.UTF8, 8192);
                sw.Write(html);
                sw.Flush();
                sw.Close();
            }
        }

        private static string traducirPartido(string html)
        {
            Regex r = null;
            string htmlTraducido = html;
            string linea = "";

            try
            {
                StreamReader sr = new StreamReader("conf\\traduccion.txt", Encoding.UTF8);

                while ((linea = sr.ReadLine()) != null)
                {
                    string[] tokens = linea.Split(new string[] { "##" }, StringSplitOptions.RemoveEmptyEntries);

                    r = new Regex(tokens[0]);
                    htmlTraducido = r.Replace(htmlTraducido, tokens[1]);
                }

                sr.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Se ha producido un error durante la traducción del reporte. Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return htmlTraducido;
        }

        private static ReportePartido parsearPartido(Partido part, string rutaHtmlEntrada)
        {
            ReportePartido reporte = new ReportePartido();

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.Load(rutaHtmlEntrada);

            HtmlNodeCollection tablas = doc.DocumentNode.SelectNodes("//table");

            //Partido
            reporte.partido = part;

            //Alineaciones
            reporte.titularesLocal = parsearJugadores(tablas[0]);
            reporte.titularesVisitante = parsearJugadores(tablas[1]);
            reporte.suplentesLocal = parsearJugadores(tablas[2]);
            reporte.suplentesVisitante = parsearJugadores(tablas[3]);

            reporte.titularesLocalFin = parsearJugadores(tablas[4]);
            reporte.titularesVisitanteFin = parsearJugadores(tablas[5]);
            reporte.suplentesLocalFin = parsearJugadores(tablas[6]);
            reporte.suplentesVisitanteFin = parsearJugadores(tablas[7]);

            //Lista de Ocasiones del Partido
            HtmlNode nodoReporte = doc.DocumentNode.SelectSingleNode("//div[@id='match-report']");
            HtmlNodeCollection grupos = nodoReporte.SelectNodes("ul");

            List<Ocasion> ocasiones = new List<Ocasion>();

            Ocasion ocasion = null;

            foreach (HtmlNode nodoGrupo in grupos)
            {
                HtmlNodeCollection jugadas = nodoGrupo.SelectNodes("li");

                foreach (HtmlNode nodoJugada in jugadas)
                {
                    string texto = nodoJugada.InnerText;

                    if (texto.StartsWith("Minuto"))
                    {
                        if (ocasion != null)
                            ocasiones.Add(ocasion);

                        ocasion = new Ocasion();
                        ocasion.jugadas = new List<string>();

                        ocasion.minuto = Convert.ToInt32(texto.Split(new char[]{' '},StringSplitOptions.RemoveEmptyEntries)[1]);
                    }
                    else if (texto.Equals("DESCANSO"))
                    {
                        if (ocasion != null)
                            ocasiones.Add(ocasion);

                        ocasion = new Ocasion();
                        ocasion.jugadas = new List<string>();

                        ocasion.minuto = -45;
                    }
                    else
                    {
                        if(!texto.Equals("&nbsp;"))
                            ocasion.jugadas.Add(texto);
                    }
                }
            }

            if (ocasion != null)
                ocasiones.Add(ocasion);

            reporte.ocasiones = ocasiones;

            return reporte;
        }

        private static List<Jugador> parsearJugadores(HtmlNode tablaJugadores)
        {
            List<Jugador> listaJugadores = new List<Jugador>();

            HtmlNodeCollection filasJugadores = tablaJugadores.SelectNodes("tr");
            foreach (HtmlNode filaJugador in filasJugadores)
            {
                HtmlNode nodoPosicion = filaJugador.SelectSingleNode("td[@class='algnR matchreport-pos']");

                if (nodoPosicion != null)
                {
                    string[] tokensPos = nodoPosicion.InnerText.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    Jugador jug = new Jugador();
                    jug.posicion = (Traductor.traducirPosicionIngles(tokensPos[0]) + " " + (tokensPos.Length>1 ? tokensPos[1] : "")).Trim();
                    jug.nacionalidad = filaJugador.SelectSingleNode("td[@class='minimal']").SelectSingleNode("img").Attributes["title"].Value;
                    jug.id = Convert.ToInt32(filaJugador.SelectSingleNode("td[@class='algnL matchreport-playername']").SelectSingleNode("a").Attributes["href"].Value.Split(new char[] { '.' })[1]);
                    jug.nombre = filaJugador.SelectSingleNode("td[@class='algnL matchreport-playername']").SelectSingleNode("a").InnerText.Trim();

                    listaJugadores.Add(jug);
                }
            }

            return listaJugadores;
        }

        public static string descargarXml(string url)
        {
            string res = null;

            try
            {
                StringBuilder sb = new StringBuilder();

                byte[] buf = new byte[8192];

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                if (FrmPrincipal.opciones.obtenerOpcion("usarProxy").Equals("1"))
                {
                    request.Proxy = new System.Net.WebProxy(FrmPrincipal.opciones.obtenerOpcion("proxyUrl") + ":" + FrmPrincipal.opciones.obtenerOpcion("proxyPuerto"), true);
                    request.Proxy.Credentials = new NetworkCredential(FrmPrincipal.opciones.obtenerOpcion("proxyUsuario"), FrmPrincipal.opciones.obtenerOpcion("proxyPassword"), FrmPrincipal.opciones.obtenerOpcion("proxyDominio"));
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    count = resStream.Read(buf, 0, buf.Length);

                    if (count != 0)
                    {
                        tempString = Encoding.UTF8.GetString(buf, 0, count);

                        sb.Append(tempString);
                    }
                }
                while (count > 0);

                res = sb.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Se ha producido un error en la descarga del fichero XML. Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                res = null;
            }

            return res;
        }

        public static bool descargarXml(string url, string path)
        {
            bool res = true;

            try
            {
                StreamWriter sw = new StreamWriter(path, false, Encoding.Default, 8192);

                StringBuilder sb = new StringBuilder();

                byte[] buf = new byte[8192];

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                if (FrmPrincipal.opciones.obtenerOpcion("usarProxy").Equals("1"))
                {
                    request.Proxy = new System.Net.WebProxy(FrmPrincipal.opciones.obtenerOpcion("proxyUrl") + ":" + FrmPrincipal.opciones.obtenerOpcion("proxyPuerto"), true);
                    request.Proxy.Credentials = new NetworkCredential(FrmPrincipal.opciones.obtenerOpcion("proxyUsuario"), FrmPrincipal.opciones.obtenerOpcion("proxyPassword"), FrmPrincipal.opciones.obtenerOpcion("proxyDominio"));
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    count = resStream.Read(buf, 0, buf.Length);

                    if (count != 0)
                    {
                        tempString = Encoding.Default.GetString(buf, 0, count);

                        sb.Append(tempString);
                    }
                }
                while (count > 0);

                sw.Write(sb.ToString());

                sw.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Se ha producido un error en la descarga del fichero XML. Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                res = false;
            }

            return res;
        }
    }
}
